
/*****************************************************************************
	Swarm Parser
	@author Rajesh
*****************************************************************************/
class SwarmParser extends Parser;
options { 
	k = 2; /* no ambiguity with bind types */
	buildAST=true; /* we want the AST! */ 
	importVocab=Swm;
}
/* literalize these: */
tokens { 
	DEFINITION;
	STATEMENT; 
	BLOCK; /* Treat all blocks equally */
	BIND;
}

/* Plain old Facet */
protected
facetunit  : FACET;

/* Facet with post - (identification | definition) 
 * rr2318: added to resolve .a -> (.left(EQUALS:eq), .b) */
protected
// need separators between units...d
facetdef : facetunit (LPAREN! unit {#facetdef = #([BLOCK,"BLOCK.UNIT_FACET"],#facetdef);} RPAREN! (facetunit)?)?;

/* Isolated or groups of facets */
protected
// BLOCKS FOR FACETS??!?!
facetblock : facetunit {#facetblock = #([BLOCK,"BLOCK.ONE_FACET"],#facetblock);}
           | LPAREN! facetdef (COMMA! facetdef)* RPAREN!
           {#facetblock = #([BLOCK,"BLOCK.FACETS"],#facetblock);};

/* Hack to add to AST */
protected
bindtype : BINDTYPE
           {#bindtype = #([BIND,"BIND"],#bindtype);};

/* Hack to add to AST */
protected
celltype: CELLTYPE {#celltype = #([BLOCK,"BLOCK.UNIT.ASSIGNMENT"],#celltype);};

/* Cell-level specifiers */
protected
unit : CELLTYPE (NEW INSTANCE {#unit = #([BLOCK,"UNIT.LABEL"],#unit);}
         | NEW! STRING {#unit = #([BLOCK,"UNIT.STRING"],#unit);}
         | /* nothing */ {#unit = #([BLOCK,"UNIT.GENERIC"],#unit);}) 
     | INSTANCE {#unit = #([BLOCK,"UNIT.INSTANCE"],#unit);}
     | anon_def {#unit = #([BLOCK,"UNIT.ANON_DEF"],#unit);};

/* Statement-level blocks:
		facetblocks
		cell blocks
 */
protected
block: facetblock (LPAREN! unit RPAREN! (facetblock)?  
             {#block = #([BLOCK,"BLOCK.UNIT_FACET"],#block);}
       | /* nothing */
     )    
     | LPAREN! unit ( (RPAREN! (facetblock)? ) 
                      {#block = #([BLOCK,"BLOCK.UNIT_FACET"],#block);} 
                    | ((COMMA! unit)+ RPAREN!) 
                      {#block = #([BLOCK,"BLOCK.UNIT_LISTS"],#block);}) 
     | unit {#block = #([BLOCK,"BLOCK.UNIT"],#block);}; 

/* Statements */
statement: block (bindtype block)*
           {#statement = #([STATEMENT,"STATEMENT"], #statement);};
			
/* Anonymous Cells */
protected
anon_def: LBRACKET! statement (END! statement)* (END!)? RBRACKET!
          {#anon_def = #([DEFINITION,"DEFINITION"], #anon_def);};

/* Cell Definitions */
definition: anon_def NEW! celltype END!
    /* rr2318: uncomment next line to print out new cell types */  
    /* { System.out.println("DEFINED CELL: " + left.getText());}/* IGNORE*/
          {#definition = #([DEFINITION,"DEFINITION.CELL"], #definition);}; 

/* For now we only check whether the input is a valid set of statements */
expr: (definition)+ EOF!;